package api

import (
	"fmt"
	"net/http"
	"strconv"

	"gitee.com/lishixi/gops/book/config"
	"gitee.com/lishixi/gops/book/controllers"
	"gitee.com/lishixi/gops/book/models"
	"gitee.com/lishixi/gops/book/response"
	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
)

// 构造函数，初始化结构体
func NewBookApiHandler() *BookApiHandler {
	return &BookApiHandler{db: config.Get().MySQL.DB(),
		svc: controllers.NewBookController()}
}

// 面向对象
// BookApiHandler 实现接口功能

// 为什么要加 svc ?
type BookApiHandler struct {
	db  *gorm.DB
	svc *controllers.BookController
}

// 注册路由
// book := server.Group("/api/books")
func (h *BookApiHandler) Register(r *gin.Engine) {
	book := r.Group("/api/books")
	book.GET("", h.ListBook)
	book.GET("/:isbn", h.GetBook)
	book.POST("", h.CreateBook)
	book.PUT("/:isbn", h.UpdateBook)
	book.DELETE("/:isbn", h.DeleteBook)
}

// 创建 book
func (h *BookApiHandler) CreateBook(ctx *gin.Context) {
	// 获取Book用户传达的参数
	ins := new(models.Book)
	if err := ctx.ShouldBindJSON(ins); err != nil {
		response.Failed(ctx, err)
		return
	}
	// 调用业务逻辑
	ins, err := h.svc.CreateBook(ctx, &ins.BookSpec)
	if err != nil {
		response.Failed(ctx, err)
		return
	}
	// book, save
	// if err := h.db.Save(ins).Error; err != nil {
	// 	response.Failed(ctx, err)
	// 	return
	// }

	ctx.JSON(http.StatusOK, ins)
	response.Success(ctx, ins)
}

// 查询 book 列表
// slect * from books
func (h *BookApiHandler) ListBook(ctx *gin.Context) {
	var books []models.Book
	if err := h.db.Find(&books).Error; err != nil {
		response.Failed(ctx, err)
		return
	}
	ctx.JSON(http.StatusOK, books)
}

// 查询 book 详情
func (h *BookApiHandler) GetBook(ctx *gin.Context) {
	strId := ctx.Param("isbn")
	id, err := strconv.ParseInt(strId, 10, 64)
	if err != nil {
		response.Failed(ctx, err)
		return
	}

	ins, err := h.svc.GetBook(ctx, &controllers.GetBookRequest{Isbn: id})
	if err != nil {
		response.Failed(ctx, err)
		return
	}
	response.Success(ctx, ins)
}

// 更新 book 对象
func (h *BookApiHandler) UpdateBook(ctx *gin.Context) {
	id := ctx.Param("isbn")

	// 获取用户参数, 读取用户的更新参数
	req := models.BookSpec{}
	if err := ctx.ShouldBindJSON(&req); err != nil {
		response.Failed(ctx, err)
		return
	}

	if err := h.db.Where("isbn = ?", id).Model(&models.Book{}).Updates(req).Error; err != nil {
		response.Failed(ctx, err)
		return
	}

	// 针对有零值的字段独立更新
	// if err := db.Where("isbn = ?", id).Model(&Book{}).Update("is_sale", req.IsSale).Error; err != nil {
	// 	Failed(ctx, err)
	// 	return
	// }
	// // ......

	// 再次查询出来
	var ins models.Book
	if err := h.db.Where("isbn = ?", id).Take(&ins).Error; err != nil {
		response.Failed(ctx, fmt.Errorf("book not found"))
		return
	}

	// 查询出更新后的数据
	response.Success(ctx, ins)
}

// 删除 book 对象
func (h *BookApiHandler) DeleteBook(ctx *gin.Context) {
	id := ctx.Param("isbn")
	if err := h.db.Where("isbn = ?", id).Delete(&models.Book{}).Error; err != nil {
		response.Failed(ctx, err)
		return
	}
}
